/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package org.neo4j.bolt.protocol.common.fsm.response.metadata;

import java.util.List;
import org.neo4j.bolt.protocol.common.fsm.response.MetadataConsumer;
import org.neo4j.graphdb.ExecutionPlanDescription;
import org.neo4j.graphdb.GqlStatusObject;
import org.neo4j.graphdb.Notification;
import org.neo4j.graphdb.QueryExecutionType;
import org.neo4j.graphdb.QueryStatistics;
import org.neo4j.kernel.database.DatabaseReference;
import org.neo4j.values.virtual.MapValue;

/**
 * Handles the protocol specific conversion of statement generated metadata.
 */
public interface MetadataHandler {

    /**
     * Consumes the statement identifier via which a given executed statement may be referenced
     * within an explicit transaction.
     *
     * @param statementId a statement identifier.
     */
    void onStatementId(MetadataConsumer consumer, long statementId);

    /**
     * Consumes the amount of time the server took in order to prepare results in order to begin
     * streaming (e.g. time between {@code RUN} and its respective {@code SUCCESS} response).
     *
     * @param spent the amount of time spent (in milliseconds).
     */
    void onTimeSpentPreparingResults(MetadataConsumer consumer, long spent);

    /**
     * Consumes the amount of time the server spent streaming (e.g. time between {@code PULL} and
     * its respective {@code SUCCESS} including network overhead).
     *
     * @param spent the amount of time spent (in milliseconds).
     */
    void onTimeSpentStreaming(MetadataConsumer consumer, long spent);

    /**
     * Consumes the names of fields returned by a statement.
     *
     * @param names a set of unique field names.
     */
    void onFieldNames(MetadataConsumer consumer, List<String> names);

    /**
     * Consumes the execution type for a given statement.
     *
     * @param executionType an execution type specification.
     */
    void onExecutionType(MetadataConsumer consumer, QueryExecutionType executionType);

    /**
     * Consumes the database on which a given statement was executed.
     *
     * @param reference a database reference.
     */
    void onDatabase(MetadataConsumer consumer, DatabaseReference reference);

    /**
     * Consumes the resolved database after a transaction has been started without a specified database.
     *
     * @param name the database name.
     */
    void onTransactionDatabase(MetadataConsumer consumer, String name);

    /**
     * Consumes the query statistics for a given statement.
     *
     * @param statistics a set of statistics.
     */
    void onQueryStatistics(MetadataConsumer consumer, QueryStatistics statistics);

    /**
     * Consumes the notifications generated while executing a given statement.
     *
     * @param notifications a set of notifications.
     * @param statuses a set of statuses, these are used in new protocol versions.
     */
    void onNotifications(
            MetadataConsumer consumer, Iterable<Notification> notifications, Iterable<GqlStatusObject> statuses);

    /**
     * Consumes the execution plan generated by an {@code EXPLAIN} statement.
     *
     * @param plan an execution plan.
     */
    void onExecutionPlan(MetadataConsumer consumer, ExecutionPlanDescription plan);

    /**
     * Notifies the handler about the remaining results within the current statement.
     *
     * @param hasRemaining true if results remain for consumption, false otherwise.
     */
    void onResultsRemaining(MetadataConsumer consumer, boolean hasRemaining);

    /**
     * Notifies the handler about the routing table generated as a result of a routing table query.
     *
     * @param databaseName the database for which the routing table is valid.
     * @param routingTable a routing table.
     */
    void onRoutingTable(MetadataConsumer consumer, String databaseName, MapValue routingTable);

    /**
     * Consumes a bookmark generated as a result of committing a transaction.
     *
     * @param encodedBookmark a bookmark referencing the committed transaction log entry/entries.
     */
    void onBookmark(MetadataConsumer consumer, String encodedBookmark);
}
